/******************* (C) COPYRIGHT 2022 CHU WEI TENG ***********************************************
**
**------------------ File Info ---------------------------------------------------------------------
** File name:      dwin_windows.c
** modified Date:  2022-05-10
** Last Version:   V1.0
** Descriptions: 
** 
**------------------ Modfication  log --------------------------------------------------------------
** Date       Who            Rev        Comments
----------------------------------------------------------------------------------------------------
   22/05/10 chuwt@qq.com    V1.00      created

****************************************************************************************************/
#include "dwin_windows.h"
#include "dwin_page.h"
#include "dwin_trans.h"

/* Private define----------------------------------------------------------------------------------*/

/* Private typedef---------------------------------------------------------------------------------*/

/* Private variables-------------------------------------------------------------------------------*/
dwin_widget_vtable_t  windows_vt = 
{
    .obj_size = sizeof(dwin_windows_t),
};

static dwin_windows_t *root = NULL;

/* Private function--------------------------------------------------------------------------------*/
static ret_t dwin_windows_parser(dwin_widget_t* windows, data_pack_t* pack)
{
    dwin_windows_t* obj = (dwin_windows_t *)windows;
    dwin_widget_t*  widget = NULL;
    dwin_list_t*    node = NULL;
    uint16_t        addr = (pack->addr_high << 8) | pack->addr_low;

    for (node = obj->list.next; node != &obj->list; node = node->next)
    {
        widget = dwin_list_entry(node, dwin_widget_t, list);

        if (widget->addr == addr)
        {
            if (widget->vt->dispatch != NULL)
            {
                widget->vt->dispatch(widget, pack);
            }
            break;
        }
        else if (widget->widget_type == DWIN_PAGE)
        {
            dwin_page_t* page = (dwin_page_t*) widget;
            
            if (page->page_id == obj->curr_page_id)
            {
                dwin_list_t* page_node = NULL;  
                
                for (page_node = page->list.next; page_node != &page->list; page_node = page_node->next)
                {
                    widget = dwin_list_entry(page_node, dwin_widget_t, list);

                    if (widget->addr == addr)
                    {
                        if (widget->vt->dispatch != NULL)
                        {
                            widget->vt->dispatch(widget, pack);
                        }
                        break;
                    }
                }
            }
        }
    }
    return RET_OK;
}

static ret_t dwin_windows_display(dwin_widget_t* windows)
{
    dwin_windows_t* obj = (dwin_windows_t *)windows;
    dwin_widget_t*  widget = NULL;
    dwin_list_t*    node = NULL;
    
    for (node = obj->list.next; node != &obj->list; node = node->next)
    {
         widget = dwin_list_entry(node, dwin_widget_t, list);
        
        if (widget->widget_type == DWIN_PAGE)
        {
            dwin_page_t* page = (dwin_page_t *)widget;
            
            if (page->page_id == obj->curr_page_id)
            {
                dwin_page_run(widget);
                break;
            }
        }
    }
    return RET_OK;
}

/* public function--------------------------------------------------------------------------------*/
ret_t dwin_windows_init(dwin_widget_t* windows)
{
    return_value_if_fail(windows, RET_BAD_PARAMS);

	root = (dwin_windows_t *)windows;
	
    dwin_windows_t* obj = (dwin_windows_t *)windows;

    DWIN_INIT_LIST_HEAD(&obj->list);

    return RET_OK;
}

ret_t dwin_windows_run(dwin_widget_t* windows)
{
    return_value_if_fail(windows, RET_BAD_PARAMS);

    data_pack_t     pack = {0};
    dwin_trans_t*   trans = dwin_trans_get();
  
    if (trans != NULL && dwin_fifo_pop(trans->data_fifo, &pack))
    {
        dwin_windows_parser(windows, &pack);
    }
    
    dwin_windows_display(windows);

    return RET_OK;
}

ret_t dwin_windows_widget_add(dwin_widget_t* windows, dwin_widget_t* widget)
{
    return_value_if_fail(windows, RET_BAD_PARAMS);
    return_value_if_fail(widget, RET_BAD_PARAMS);

    dwin_windows_t* obj = (dwin_windows_t *)windows;
    
    dwin_list_add(&widget->list, &obj->list);
    
    return RET_OK;
}

ret_t dwin_windows_widget_remove(dwin_widget_t* widget)
{
    return_value_if_fail(widget, RET_BAD_PARAMS);

    dwin_list_del(&widget->list);

    return RET_OK;
}


ret_t dwin_windwos_curr_page_set(dwin_widget_t* windows, uint16_t page_id)
{
    return_value_if_fail(windows, RET_BAD_PARAMS);
    dwin_windows_t* obj = (dwin_windows_t *)windows;
    obj->curr_page_id = page_id;
    
    return RET_OK;
}

ret_t dwin_windows_jump(uint16_t page_id)
{
	dwin_windows_t* obj = (dwin_windows_t *)root;
    dwin_widget_t*  widget = NULL;
    dwin_list_t*    node = NULL;
    
    for (node = obj->list.next; node != &obj->list; node = node->next)
    {
        widget = dwin_list_entry(node, dwin_widget_t, list);
        
        if (widget->widget_type == DWIN_PAGE)
        {
            dwin_page_t* page = (dwin_page_t *)widget;
            
            if (page->page_id == page_id)
            {
                dwin_windwos_curr_page_set((dwin_widget_t*)obj, page->page_id);
    
				dwin_page_open((dwin_widget_t*)page);
				
				dwin_page_jump((dwin_widget_t*)page);
				
                break;
            }
        }
    }
	
	return RET_OK;
}
